package online.heycm.rbac.common.config.filter;

import online.heycm.platform.common.entity.result.Result;
import online.heycm.platform.common.tools.IOUtil;
import online.heycm.platform.redis.RedisCache;
import online.heycm.rbac.common.cache.InterfaceCache;
import online.heycm.rbac.common.cache.RolePermitCache;
import online.heycm.rbac.common.config.RequestContext;
import online.heycm.rbac.common.constant.Constant;
import online.heycm.rbac.common.constant.ErrorCode;
import online.heycm.rbac.common.entity.InterfaceDef;
import online.heycm.rbac.common.entity.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

import static online.heycm.platform.common.entity.constant.Constant.AUTHORIZATION;
import static online.heycm.platform.common.entity.constant.Constant.TOKEN_PREFIX;

/**
 * 认证权限
 *
 * @author hey
 * @version 1.0
 * @date 2024/1/11 11:47
 */
@Component
public class AuthFilter extends OncePerRequestFilter implements Ordered {

    @Value("${spring.profiles.active}")
    private String active;

    @Autowired
    private RedisCache redisCache;

    @Override
    public int getOrder() {
        return 0;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        // 请求资源
        String path = request.getRequestURI();
        // 放行接口文档
        if ("dev".equals(active) && path.startsWith("/app/doc")) {
            chain.doFilter(request, response);
            return;
        }

        // 获取访问接口信息
        InterfaceDef interfaceDef = InterfaceCache.get(path);
        if (interfaceDef == null) {
            IOUtil.writeJson(response, Result.error(ErrorCode.ERROR_RESOURCE));
            return;
        }

        // 开放接口直接放行
        if (!interfaceDef.isAuthApi()) {
            chain.doFilter(request, response);
            return;
        }

        // 获取session
        String token = request.getHeader(AUTHORIZATION);
        if (!(StringUtils.hasText(token) && token.length() == 39 && token.startsWith(TOKEN_PREFIX))) {
            IOUtil.writeJson(response, Result.error(ErrorCode.ERROR_AUTH));
            return;
        }
        token = token.substring(7);
        Session session = redisCache.hGet(String.format(Constant.SESSION_KEY, token), Session.class);
        if (session == null) {
            IOUtil.writeJson(response, Result.error(ErrorCode.ERROR_AUTH));
            return;
        }

        // 权限校验
        if (!RolePermitCache.check(session.getRoleCodes(), interfaceDef)) {
            IOUtil.writeJson(response, Result.error(ErrorCode.ERROR_PERMIT));
            return;
        }

        try {
            RequestContext.set(session);
            chain.doFilter(request, response);
        } finally {
            RequestContext.remove();
        }
    }
}
